﻿#ifndef __AVOID_BW_CONTROL_CONTROL_HEAD_FILE_INCLUDED__
#define __AVOID_BW_CONTROL_CONTROL_HEAD_FILE_INCLUDED__
#include "ctlDefine.h"
#include "ctlText.h"
#include "ctlHelp.h"
#include "ctlFontQueue.h"
#include "ctlImageQueue.h"
#include "x/textpack.h"
#include "x/eventTranslate.h"
#include <map>
#include <unordered_map>
#include <ctime>
#include <memory>
#include <string>
#include <typeinfo>
#include <type_traits>
#include <functional>

namespace swui
{
	typedef std::vector<ctlRoot*> controlList;
	class ctlRoot
	{
		ctlRoot(const ctlRoot&);
		friend class ctlList;
		friend class _ctlInterior::eventTranslator;
	public:
		static const ctlControlType uniqueType = ctlControlType::ctlUndefined;
	public:
		static ctlRoot* init(ctlInitInfo*);
		static bool uninit(ctlInitInfo*);
	public:
		typedef void(*ptrMouseEvent)(ctlRoot*, ctlMouseEvent*);
		typedef void(*ptrKeyEvent)(ctlRoot*, ctlKeyEvent*);
		typedef void(*ptrPositionEvent)(ctlRoot*, ctlPositionEvent*);
		typedef void(*ptrNotifyEvent)(ctlRoot*, ctlNotifyEvent*);
		typedef std::function<void(ctlRoot*, ctlMouseEvent*)> lamMouseEvent;
		typedef std::function<void(ctlRoot*, ctlKeyEvent*)> lamKeyEvent;
		typedef std::function<void(ctlRoot*, ctlPositionEvent*)> lamPositionEvent;
		typedef std::function<void(ctlRoot*, ctlNotifyEvent*)> lamNotifyEvent;
	public:
		virtual ~ctlRoot();
		ctlRoot();
	public:
		//销毁控件
		virtual void destroy();
		//判断是否创建
		bool isCreated();
	public:
		//获取字体队列
		std::shared_ptr<ctlFontQueue> getFontQueue();
		//获取图像队列
		std::shared_ptr<ctlImageQueue> getImageQueue();
		//获取初始化时的编码
		bool isUnicode();
	public:
		enum class moveFormat : unsigned
		{
			absolute,	//相对于父级元素定位
			percent,	//相对于父级元素，以百分比定位
			relative		//相对于另外一个元素（必须是同级或父级元素）
		};
		enum class sizeFormat : unsigned
		{
			relative,		/*如果相对于父级元素定位，this.getRight() = parent.getWidth() - offsetX
							 *如果相对于同级元素定位，this.getRight() = relation.getLeft() - offsetX */
			absolute,	//相对于父级元素定位
			percent		//相对于父级元素，以百分比定位
		};
		enum class moveAlignment : unsigned
		{
			leftTop = 0x00, leftMiddle = 0x01, leftBottom = 0x02,
			middleTop = 0x10, middle = 0x11, middleBottom = 0x12,
			rightTop = 0x20, rightMiddle = 0x21, rightBottom = 0x22
		};
	public:
		//获取控件 Z 序（从 0 开始）
		unsigned getZOrder();
		//设置控件 Z 序（最大只能是 getParent()->getChildren().size() - 1）
		virtual bool setZOrder(unsigned);
		//设置控件 Z 序在指定控件之后
		bool setZOrderAfter(ctlRoot*);
		//设置控件 Z 序在指定控件之前
		bool setZOrderBefore(ctlRoot*);
		/* 设置控件为顶层控件
		 * 如果还有其它（兄弟）控件也调用这个函数
		 * 那么这个控件会变为第二层（在那个控件之下）
		 * 但是新加入的控件还是不会改变这个控件的 ZOrder */
		bool setZOrderTop();
		//获取在顶层的子控件数目
		unsigned getChildrenZOrderTopNumber();
		//获取控件相对于父级元素的位置
		int getWidth();
		int getHeight();
		int getLeft();
		int getTop();
		int getRight();
		int getBottom();
		ctlRect getRect();
		ctlRect getAbsoluteRect();
		//无关定位方式，获取数据
		float getPercentLeft();
		float getPercentTop();
		float getPercentWidth();
		float getPercentHeight();
		ctlRectTemplate<float> getPercentRect();
	public:
		/* 设置位置格式，位置会根据格式以及当前绝对位置自动进行计算
		 *  对于 move 的 relative 格式，如果出现环状关联，那么函数返回 false
		 *  即 A 关联到 B、B 关联到 C、这样数次后又关联回 A	 */
		bool setMoveFormat(moveFormat, ctlDirection, ctlRoot* relation = nullptr);
		moveFormat getMoveFormat(ctlDirection);
		bool setSizeFormat(sizeFormat, ctlDirection, ctlRoot* relation = nullptr);
		sizeFormat getSizeFormat(ctlDirection);
		//判断是否拥有某种位置格式（x 或 y 有任意一个拥有就算拥有)
		bool hasMoveFormat(moveFormat);
		bool hasSizeFormat(sizeFormat);
		//设置 relative 的 move 的基准（move 定位必须为 relative）
		bool setMoveAlignment(moveAlignment all);
		bool setMoveAlignment(moveAlignment me, moveAlignment relation);
		moveAlignment getThisMoveAlignment();
		moveAlignment getRelationMoveAlignment();
	public:
		//移动位置，定位方式必须为 relative
		bool moveRelative(int x, int y, ctlDirection = ctlDirection::xy, ctlRoot* relation = nullptr);
		//快速设置 move.relative 格式
		bool setRelativeMoveFormat(ctlDirection, int x, int y, ctlRoot* rx, ctlRoot* ry,
			moveAlignment ame, moveAlignment arelation);
		bool setRelativeMoveFormat(ctlDirection, int x, int y, ctlRoot* rx, ctlRoot* ry,
			moveAlignment all = moveAlignment::leftTop);
		//获取 move 的 relative 定位的关联对象，如果不是 relative 定位，则返回 nullptr
		ctlRoot* getMoveRelation(ctlDirection dir);
	public:
		//调整大小，定位方式必须为 percent
		//100% 用浮点数 1.0f 表示， 不支持负值
		bool sizePercent(float cx, float cy, ctlDirection = ctlDirection::xy);
		//快速设置 size.percent 格式
		bool setPercentSizeFormat(ctlDirection, float cx, float cy);
		//移动位置，定位方式必须为 percent
		//100% 用浮点数 1.0f 表示， 支持负值
		bool movePercent(float cx, float cy, ctlDirection = ctlDirection::xy);
		//快速设置 move.percent 格式
		bool setPercentMoveFormat(ctlDirection, float cx, float cy);
	public:
		//调整大小，定位方式必须为 relative 族
		bool sizeRelative(int rightOffset, int bottomOffset,
			ctlDirection = ctlDirection::xy, ctlRoot* relation = nullptr);
		//快速设置 size.relative 格式
		bool setRelativeSizeFormat(ctlDirection, int x, int y, ctlRoot* rx, ctlRoot* ry);
		//获取 size 的 relative 定位的关联对象，如果不是 relative 定位，则返回 nullptr
		ctlRoot* getSizeRelation(ctlDirection dir);
	public:
		//调整大小（若 absolute == false 则相对于当前大小加上 [cx, cy]）
		//定位方式必须为 absolute
		bool size(int cx, int cy, bool absolute = true);
		bool size(ctlPoint point, bool absolute = true);
		//移动控件（若 absolute == false 则相对于当前位置平移，否则x和y代表相对于父控件的坐标）
		//定位方式必须为 absolute
		bool move(int x, int y, bool absolute = true);
		bool move(ctlPoint point, bool absolute = true);
		//打开位置锁，锁定后 move 和 size 函数失效（可以嵌套使用）
		void lockPosition();
		//关闭位置锁（如果位置锁没有打开，这个函数不会有任何效果）
		void unlockPosition();
		//判断位置锁是否打开
		bool isPositionLocked();
		//获得位置锁锁定次数
		unsigned getPositionLockCount();
	public:
		//获取控件类型
		ctlControlType getControlType();
		//获得根控件
		ctlRoot* getRoot();
		//获得父控件
		ctlRoot* getParent();
		//获得继承深度（根控件为0）
		unsigned getInheritDepth();
		//获得子控件列表（type 为 ctlUndefined 即获取全部子控件）
		controlList getChildren(ctlControlType type = ctlControlType::ctlUndefined);
		//根据索引获取子控件
		ctlRoot* getChild(unsigned index);
		//获取子控件迭代器
		controlList::const_iterator begin();
		controlList::const_iterator end();
	public:
		/* 添加鼠标事件到普通函数队列（事件名，事件处理过程，[额外参数]）
			*  事件处理过程 void functionName(ctlRoot*, ctlMouseEvent*);  */
		void addEvent(ctlMouseEventType eventType, ptrMouseEvent method, ctlMouseEvent::paramType param = 0);
		//从普通函数队列移除事件，只比较函数地址
		bool removeEvent(ctlMouseEventType eventType, ptrMouseEvent method);
		//从普通函数队列移除事件，比较附加参数和函数地址
		bool removeEvent(ctlMouseEventType eventType, ptrMouseEvent method, ctlMouseEvent::paramType param);
	public:
		/* 添加鼠标事件到 Lambda 函数队列（事件名，事件处理过程，[额外参数]）
		 *  事件处理过程 void functionName(ctlRoot*, ctlMouseEvent*);
		 * 返回值在删除事件处理器时使用 */
		unsigned addLambdaEvent(ctlMouseEventType eventType, lamMouseEvent method, ctlMouseEvent::paramType param = 0);
		//从 Lambda 函数队列移除事件，根据添加时返回的值
		bool removeLambdaEvent(ctlMouseEventType eventType, unsigned id);
	public:
		/* 添加键盘事件到普通函数队列（事件名，事件处理过程，[额外参数]）
			*  事件处理过程 void functionName(ctlRoot*, ctlKeyEvent*);  */
		void addEvent(ctlKeyEventType eventType, ptrKeyEvent method, ctlKeyEvent::paramType param = 0);
		//从普通函数队列移除事件，只比较函数地址
		bool removeEvent(ctlKeyEventType eventType, ptrKeyEvent method);
		//从普通函数队列移除事件，比较附加参数和函数地址
		bool removeEvent(ctlKeyEventType eventType, ptrKeyEvent method, ctlKeyEvent::paramType param);
	public:
		/* 添加键盘事件到 Lambda 函数队列（事件名，事件处理过程，[额外参数]）
		 *  事件处理过程 void functionName(ctlRoot*, ctlKeyEvent*);
		 * 返回值在删除事件处理器时使用 */
		unsigned addLambdaEvent(ctlKeyEventType eventType, lamKeyEvent method, ctlKeyEvent::paramType param = 0);
		//从 Lambda 函数队列移除事件，根据添加时返回的值
		bool removeLambdaEvent(ctlKeyEventType eventType, unsigned id);
	public:
		/* 添加位置事件到普通函数队列（事件名，事件处理过程，[额外参数]）
	 	 *  事件处理过程 void functionName(ctlRoot*, ctlPositionEvent*);  */
		void addEvent(ctlPositionEventType eventType, ptrPositionEvent method, ctlPositionEvent::paramType param = 0);
		//从普通函数队列移除事件，只比较函数地址
		bool removeEvent(ctlPositionEventType eventType, ptrPositionEvent method);
		//从普通函数队列移除事件，比较附加参数和函数地址
		bool removeEvent(ctlPositionEventType eventType, ptrPositionEvent method, ctlPositionEvent::paramType param);
	public:
		/* 添加位置事件到 Lambda 函数队列（事件名，事件处理过程，[额外参数]）
		 * 事件处理过程 void functionName(ctlRoot*, ctlPositionEvent*);
		 * 返回值在删除事件处理器时使用 */
		unsigned addLambdaEvent(ctlPositionEventType eventType, lamPositionEvent method, ctlPositionEvent::paramType param = 0);
		//从 Lambda 函数队列移除事件，根据添加时返回的值
		bool removeLambdaEvent(ctlPositionEventType eventType, unsigned id);
	public:
		/* 添加通告事件到普通函数队列（事件名，事件处理过程，[额外参数]）
			*  事件处理过程 void functionName(ctlRoot*, ctlNotifyEvent*);  */
		void addEvent(ctlNotifyEventType eventType, ptrNotifyEvent method, ctlNotifyEvent::paramType param = 0);
		//从普通函数队列移除事件，只比较函数地址
		bool removeEvent(ctlNotifyEventType eventType, ptrNotifyEvent method);
		//从普通函数队列移除事件，比较附加参数和函数地址
		bool removeEvent(ctlNotifyEventType eventType, ptrNotifyEvent method, ctlNotifyEvent::paramType param);
	public:
		/* 添加通告事件到 Lambda 函数队列（事件名，事件处理过程，[额外参数]）
		 *  事件处理过程 void functionName(ctlRoot*, ctlNotifyEvent*);
		 * 返回值在删除事件处理器时使用 */
		unsigned addLambdaEvent(ctlNotifyEventType eventType, lamNotifyEvent method, ctlNotifyEvent::paramType param = 0);
		//从 Lambda 函数队列移除事件，根据添加时返回的值
		bool removeLambdaEvent(ctlNotifyEventType eventType, unsigned id);
	public:
		//设置控件样式
		virtual void setStyle(const ctlStyleBase&);
		//获取控件样式
		std::shared_ptr<ctlStyleBase> getStyle();
		ctlStyleBase& getStyleRef();
		//设置控件的透明度
		void setControlAlpha(unsigned char alpha);
		//获取控件透明度
		unsigned char getControlAlpha();
		//隐藏控件
		void hide();
		//显示控件
		void show();
		//检测控件是否在屏幕上可见（只要 祖先控件 有一个不可视就是 false）
		bool isVisible();
		//检测控件本身显示状态（与 祖先控件 无关）
		bool isShow();
	public:
		/* 打开重绘锁，使 redraw 和 redrawAllControl 失效（可以嵌套）
		 * 如果 isAll == true，影响所有控件，否则只锁当前控件 */
		void lockDrawing(bool isAll = true);
		//关闭重绘锁（如果重绘锁没有打开，这个函数不会有任何效果）
		void unlockDrawing(bool isAll = true);
		//判断重绘锁是否打开
		bool isDrawingLocked(bool isAll = true);
		//获得重绘锁锁定次数
		unsigned getDrawingLockCount(bool isAll = true);
		//重绘整个窗体
		void redrawAllControl();
		//只重绘当前控件及其父控件
		void redraw();
		//重绘指定区域
		void redrawRect(ctlRect rect, bool absolute = false);
		//获取上一次重绘耗时
		std::clock_t getPreDrawTimeCost();
	public:
		//捕获鼠标移动事件（即将 move 事件直接发送到当前控件）
		void captureMouseMove();
		//释放鼠标移动事件捕获
		void releaseMouseMove();
	public:
		//设置鼠标事件模型
		void setMouseEventModel(ctlMouseEventModel model);
		//获取鼠标事件模型
		ctlMouseEventModel getMouseEventModel();
	public:
		//设置文字信息（有可能有的控件不需要）
		virtual bool setText(const ctlText& lpszText);
		//返回文字的长度（这里的长度不是所占内存多少，而是字符个数）
		virtual unsigned getTextLength();
		//返回文字以多字节计数所需的内存
		virtual unsigned getANSITextSize();
		//获取文字，返回的是拷贝出来的文字长度
		virtual unsigned getText(char* lpszText, unsigned bufferLen = 0);
		//获取文字，返回的是拷贝出来的文字长度
		virtual unsigned getText(std::wstring::pointer lpszText, unsigned bufferLen = 0);
		//获取文字
		virtual std::string getText();
		//获取文字
		virtual std::wstring getWideText();
	public:
		//获取当前焦点所在的控件指针
		ctlRoot* getFocus();
		//将焦点移到当前控件
		void setFocus();
		//将焦点移除
		void killFocus();
		//若当前控件将要得到焦点，则转让给指定的控件
		//为 nullptr 则不转让
		bool setFocusAssign(ctlRoot* assign);
		ctlRoot* getFocusAssign();
	public:
		//设置用户自己的数据
		void setUserData(unsigned);
		//获得用户自己的数据
		unsigned getUserData();
	public:
		//设置控件是否可用（true 为可用）
		void enable(bool is, bool doChildren = true);
		//判断控件是否可用
		bool isEnabled();
	public:
		//判断鼠标是否停留在当前控件
		bool isMouseStay();
		//判断鼠标是否在当前控件按下而没有松开
		bool isMouseDown();
		//判断相对于当前控件的点是否在当前控件上
		bool isPointInControl(ctlPoint point);
	public:
		//在控件销毁之后会自动释放没有释放的内存
		//分配失败返回 nullptr
		void* heapAlloc(size_t size, void(*deleter)(void*));
		void heapFree(void*);
	public:
		//获取当前重绘频率
		unsigned getRedrawFrequency();
		//设置当前重绘频率（影响所有控件）
		void setRedrawFrequency(unsigned frequency);
	public:
		//转换到指定的派生类（类似 dynamic_cast）
		template<typename CastTo>
		CastTo castTo();
	protected:
		//内部事件处理
		virtual void _mouse_event_(ctlMouseEvent*);	//这里的实现提供外部事件的发送
		virtual void _key_event_(ctlKeyEvent*);				//同上
		virtual void _position_event_(ctlPositionEvent*);
		virtual void _notify_event_(ctlNotifyEvent*);
		virtual void _redraw_(_ctlInterior::drawInfo*) = 0;
		virtual void _alpha_redraw_(_ctlInterior::drawInfo*);
		virtual bool _judge_point_(ctlPoint);		//默认为按照矩形判断
		virtual bool _combine_child_rgn(HRGN);
	protected:
		//获取绘制和事件处理迭代器
		virtual std::vector<ctlRoot*>::const_pointer _get_redraw_begin(unsigned);
		virtual unsigned _get_redraw_end(unsigned);
		virtual std::vector<ctlRoot*>::const_pointer _get_event_begin(unsigned);
		virtual unsigned _get_event_end(unsigned);
		virtual unsigned _get_redraw_or_event_number();
	protected:
		void _basic_create_(ctlRect, ctlRoot*);
		void _capture_mouse_move();
		void _release_mouse_move();
	protected:
		ctlStyleBase* _styleBase;
		_ctlInterior::textpack _textpack;
		_ctlInterior::eventTranslator _eventTrans;
		ctlControlType _controlType;
		ctlRect _rect;
		void *_control_virtual_class_end;
	private:
		unsigned char _controlAlpha;
		bool _isShow, _isEnabled;
		ctlRoot* _parent, *_focus_assign;
		int _positionLockCount;
		std::atomic_uint _redrawLockCount;
		ctlMouseEventModel _mouse_event_model;
		std::unordered_map<char*, void(*)(void*)> _heap_alloc_recorder;
		void _control_destroy(bool isAllChild);
	private:
		_ctlInterior::positionFormat<moveFormat> _moveX, _moveY;
		moveAlignment _moveThisAlignment, _moveRelationAlignment;
		_ctlInterior::positionFormat<sizeFormat> _sizeX, _sizeY;
		std::unordered_map<ctlRoot*, unsigned> _size_related, _move_related;
		void _size_change();
		void _move_change();
		ctlPoint _calc_move_relative(ctlRoot* relation, ctlDirection dir);
	private:
#define _eventListType(aaPtr, aaEvent) std::map<ctl##aaEvent##EventType, \
_ctlInterior::eventContain<aaPtr##aaEvent##Event, ctl##aaEvent##Event::paramType>>
		_eventListType(ptr, Mouse) _mouse_method;
		_eventListType(ptr, Key) _key_method;
		_eventListType(ptr, Position) _position_method;
		_eventListType(ptr, Notify) _notify_method;
		static LRESULT CALLBACK _ctlCallBack(HWND, UINT, WPARAM, LPARAM);
#undef _eventListType
	};

	inline ctlRoot::ctlRoot() {
		_styleBase = 0;
		_parent = 0;
		_controlType = ctlControlType::ctlUndefined;
	}
	inline bool ctlRoot::setMoveAlignment(moveAlignment all)
	{
		return setMoveAlignment(all, all);
	}
	inline void ctlRoot::setControlAlpha(unsigned char alpha)
	{
		_controlAlpha = alpha;
		redraw();
	}
	inline unsigned char ctlRoot::getControlAlpha()
	{
		return _controlAlpha;
	}
	//继承信息
	inline unsigned ctlRoot::getInheritDepth()
	{
		unsigned depth = 0;
		for(ctlRoot* pre = getParent();
			pre; ++depth, pre = pre->getParent());
		return depth;
	}
	inline ctlRoot* ctlRoot::getParent() {
		return _parent;
	}
	inline ctlRoot* ctlRoot::getRoot() {
		return _eventTrans.getTopest();
	}
	inline bool ctlRoot::isCreated() {
		return getControlType() != ctlControlType::ctlUndefined;
	}
	inline ctlControlType ctlRoot::getControlType()
	{
		return _controlType;
	}
	//禁用属性
	inline void ctlRoot::enable(bool is, bool child) {
		_isEnabled = is;
		lockDrawing(false);
		if(child)
		{
			for(ctlRoot* elem : getChildren())
				elem->enable(is, child);
		}
		unlockDrawing(false);
		if(is)
		{
			_move_change();
			_size_change();
		}
		redraw();
	}
	inline bool ctlRoot::isEnabled() {
		return _isEnabled;
	}
	//位置锁
	inline void ctlRoot::lockPosition() {
		++_positionLockCount;
	}
	inline void ctlRoot::unlockPosition() {
		if(_positionLockCount != 0) --_positionLockCount;
	}
	inline bool ctlRoot::isPositionLocked() {
		return _positionLockCount != 0;
	}
	inline unsigned ctlRoot::getPositionLockCount() {
		return _positionLockCount;
	}
	//坐标
	inline int ctlRoot::getWidth() { return _rect.cx; }
	inline int ctlRoot::getHeight() { return _rect.cy; }
	inline int ctlRoot::getLeft() { return _rect.x; }
	inline int ctlRoot::getTop() { return _rect.y; }
	inline int ctlRoot::getRight() { return _rect.cx + _rect.x; }
	inline int ctlRoot::getBottom() { return _rect.cy + _rect.y; }
	inline ctlRect ctlRoot::getRect() { return _rect; }
	inline bool ctlRoot::size(ctlPoint point, bool absolute) {
		return size(point.x, point.y, absolute);
	}
	inline bool ctlRoot::move(ctlPoint point, bool absolute) {
		return move(point.x, point.y, absolute);
	}
	//重绘锁
	inline bool ctlRoot::isDrawingLocked(bool isAll) {
		return getDrawingLockCount(isAll) != 0;
	}
	//显示隐藏
	inline void ctlRoot::show() {
		_isShow = true;
		redraw();
	}
	inline void ctlRoot::hide() {
		_isShow = false;
		redraw();
	}
	inline bool ctlRoot::isShow() {
		return _isShow;
	}
	//鼠标状态
	inline bool ctlRoot::isMouseStay() {
		return _eventTrans.getMajorInfo()->mouseStay == this;
	}
	inline bool ctlRoot::isMouseDown() {
		return _eventTrans.getMajorInfo()->mouseCapture == this;
	}
	inline void ctlRoot::setMouseEventModel(ctlMouseEventModel model) {
		_mouse_event_model = model;
	}
	inline ctlMouseEventModel ctlRoot::getMouseEventModel() {
		return _mouse_event_model;
	}
	//焦点
	inline ctlRoot* ctlRoot::getFocus() {
		return _eventTrans.getMajorInfo()->focus;
	}
	inline void ctlRoot::setFocus() {
		if(getFocusAssign() == nullptr)
			_eventTrans.setFocus();
		else getFocusAssign()->setFocus();
	}
	inline void ctlRoot::killFocus() {
		_eventTrans.killFocus();
	}
	inline ctlRoot* ctlRoot::getFocusAssign() {
		return _focus_assign;
	}
	inline bool ctlRoot::setFocusAssign(ctlRoot* assign) {
		ctlRoot* ass = assign;
		while(ass)
		{
			if(ass == this)
				return false;
			ass = ass->getFocusAssign();
		}
		_focus_assign = assign;
		return true;
	}
	inline float ctlRoot::getPercentLeft() {
		return (float)getLeft() / (float)_eventTrans.getParentRect().cx;
	}
	inline float ctlRoot::getPercentTop() {
		return (float)getTop() / (float)_eventTrans.getParentRect().cy;
	}
	inline float ctlRoot::getPercentWidth() {
		return (float)getWidth() / (float)_eventTrans.getParentRect().cx;
	}
	inline float ctlRoot::getPercentHeight() {
		return (float)getHeight() / (float)_eventTrans.getParentRect().cy;
	}
#define QUAL_TYPE_RETURN(category, data)	\
		if(dir == ctlDirection::y)\
			return _##category##Y.data;\
		return _##category##X.data;
	inline ctlRoot::moveFormat ctlRoot::getMoveFormat(ctlDirection dir) {
		QUAL_TYPE_RETURN(move, format);
	}
	inline ctlRoot::sizeFormat ctlRoot::getSizeFormat(ctlDirection dir) {
		QUAL_TYPE_RETURN(size, format);
	}
#undef QUAL_TYPE_RETURN
	inline ctlRoot::moveAlignment ctlRoot::getThisMoveAlignment()
	{
		return _moveThisAlignment;
	}
	inline ctlRoot::moveAlignment ctlRoot::getRelationMoveAlignment()
	{
		return _moveRelationAlignment;
	}
	inline ctlRoot* ctlRoot::getMoveRelation(ctlDirection dir) {
		if(dir == ctlDirection::y)
		{
			if(getMoveFormat(ctlDirection::y) == moveFormat::relative)
				return _moveY.relation;
			else return nullptr;
		}
		if(getMoveFormat(ctlDirection::x) == moveFormat::relative)
			return _moveX.relation;
		return nullptr;
	}
	inline ctlRoot* ctlRoot::getSizeRelation(ctlDirection dir) {
		if(dir == ctlDirection::y)
		{
			if(getSizeFormat(ctlDirection::y) == sizeFormat::relative)
				return _sizeY.relation;
			else return nullptr;
		}
		if(getSizeFormat(ctlDirection::x) == sizeFormat::relative)
			return _sizeX.relation;
		return nullptr;
	}
	inline bool ctlRoot::hasMoveFormat(moveFormat format) {
		return getMoveFormat(ctlDirection::x) == format
			|| getMoveFormat(ctlDirection::y) == format;
	}
	inline bool ctlRoot::hasSizeFormat(sizeFormat format) {
		return getSizeFormat(ctlDirection::x) == format
			|| getSizeFormat(ctlDirection::y) == format;
	}
	inline void ctlRoot::captureMouseMove() {
		_capture_mouse_move();
	}
	inline void ctlRoot::releaseMouseMove() {
		_release_mouse_move();
	}
	inline bool ctlRoot::isUnicode() {
		return _eventTrans.getMajorInfo()->isUnicode;
	}
	inline bool ctlRoot::isPointInControl(ctlPoint pt)
	{
		pt.x += getLeft();
		pt.y += getTop();
		ctlNotifyEvent ne;
		ne.eventType = ctlNotifyEventType::hittest;
		ctlNotifyHittest nh;
		ne.info = &nh;
		bool _is_in_control = false;
		nh.isInControl = &_is_in_control;
		nh.mousePos = ctlPoint(getLeft(), getTop());
		ctlRect ar = getAbsoluteRect();
		nh.absolutePos = ctlPoint(ar.getLeft(), ar.getTop());
		_notify_event_(&ne);
		return _judge_point_(pt) || _is_in_control;
	}
	inline ctlStyleBase& ctlRoot::getStyleRef()
	{
		return *_styleBase;
	}
	inline bool ctlRoot::setRelativeMoveFormat(ctlDirection dir, int x, int y,
		ctlRoot* rx, ctlRoot* ry, moveAlignment ame, moveAlignment arelation)
	{
		if(!enumTypeAndIsNull(dir, ctlDirection::x))
			setMoveFormat(moveFormat::relative, ctlDirection::x, rx);
		if(!enumTypeAndIsNull(dir, ctlDirection::y))
			setMoveFormat(moveFormat::relative, ctlDirection::y, ry);
		setMoveAlignment(ame, arelation);
		return moveRelative(x, y, dir);
	}
	inline bool ctlRoot::setRelativeMoveFormat(ctlDirection dir, int x, int y,
		ctlRoot* rx, ctlRoot* ry, moveAlignment all)
	{
		return setRelativeMoveFormat(dir, x, y, rx, ry, all, all);
	}
	inline bool ctlRoot::setRelativeSizeFormat(ctlDirection dir, int x, int y, ctlRoot* rx, ctlRoot* ry)
	{
		if(!enumTypeAndIsNull(dir, ctlDirection::x))
			setSizeFormat(sizeFormat::relative, ctlDirection::x, rx);
		if(!enumTypeAndIsNull(dir, ctlDirection::y))
			setSizeFormat(sizeFormat::relative, ctlDirection::y, ry);
		return sizeRelative(x, y, dir);
	}
	inline bool ctlRoot::setPercentSizeFormat(ctlDirection dir, float cx, float cy)
	{
		setSizeFormat(sizeFormat::percent, dir);
		return sizePercent(cx, cy);
	}
	inline bool ctlRoot::setPercentMoveFormat(ctlDirection dir, float cx, float cy)
	{
		setMoveFormat(moveFormat::percent, dir);
		return movePercent(cx, cy);
	}
	// Lambda 事件处理器
	template<typename EventType, typename EventStruct>
	struct ctlLambdaEventCallStruct
	{
		EventType eventMethod;
		typename EventStruct::paramType param;
		static void eventDeal(ctlRoot* object, EventStruct *es)
		{
			const ctlLambdaEventCallStruct *info
				 = reinterpret_cast<const ctlLambdaEventCallStruct*>(es->userParam);
			es->userParam = info->param;
			auto vf = info->eventMethod;
			vf(object, es);
		}
		template<typename EventTypeType>
		static unsigned addEvent(ctlRoot* th, EventTypeType eventType,
			EventType method, typename EventStruct::paramType param)
		{
			typedef ctlLambdaEventCallStruct<EventType, EventStruct> type;
			type *es = new(th->heapAlloc(sizeof(type), ctlDestructor<type>::deleter))type;
			es->eventMethod = method;
			es->param = param;
			th->addEvent(eventType, es->eventDeal,
				reinterpret_cast<typename EventStruct::paramType>(es));
			return reinterpret_cast<unsigned>(es);
		}
	};
	inline unsigned ctlRoot::addLambdaEvent(ctlMouseEventType eventType,
		lamMouseEvent method, ctlMouseEvent::paramType param)
	{
		return ctlLambdaEventCallStruct<lamMouseEvent,
			ctlMouseEvent>::addEvent(this, eventType, method, param);
	}
	inline unsigned ctlRoot::addLambdaEvent(ctlKeyEventType eventType,
		lamKeyEvent method, ctlKeyEvent::paramType param)
	{
		return ctlLambdaEventCallStruct<lamKeyEvent,
			ctlKeyEvent>::addEvent(this, eventType, method, param);
	}
	inline unsigned ctlRoot::addLambdaEvent(ctlPositionEventType eventType,
		lamPositionEvent method, ctlPositionEvent::paramType param)
	{
		return ctlLambdaEventCallStruct<lamPositionEvent,
			ctlPositionEvent>::addEvent(this, eventType, method, param);
	}
	inline unsigned ctlRoot::addLambdaEvent(ctlNotifyEventType eventType,
		lamNotifyEvent method, ctlNotifyEvent::paramType param)
	{
		return ctlLambdaEventCallStruct<lamNotifyEvent,
			ctlNotifyEvent>::addEvent(this, eventType, method, param);
	}
	inline bool ctlRoot::removeLambdaEvent(ctlPositionEventType eventType, unsigned id)
	{
		typedef ctlLambdaEventCallStruct<lamPositionEvent, ctlPositionEvent> type;
		type* value = reinterpret_cast<type*>(id);
		bool result = removeEvent(eventType, type::eventDeal,
			reinterpret_cast<ctlPositionEvent::paramType>(id));
		if(result) heapFree(value);
		return result;
	}
	inline bool ctlRoot::removeLambdaEvent(ctlKeyEventType eventType, unsigned id)
	{
		typedef ctlLambdaEventCallStruct<lamKeyEvent, ctlKeyEvent> type;
		type* value = reinterpret_cast<type*>(id);
		bool result = removeEvent(eventType, type::eventDeal,
			reinterpret_cast<ctlKeyEvent::paramType>(id));
		if(result) heapFree(value);
		return result;
	}
	inline bool ctlRoot::removeLambdaEvent(ctlNotifyEventType eventType, unsigned id)
	{
		typedef ctlLambdaEventCallStruct<lamNotifyEvent, ctlNotifyEvent> type;
		type* value = reinterpret_cast<type*>(id);
		bool result = removeEvent(eventType, type::eventDeal,
			reinterpret_cast<ctlNotifyEvent::paramType>(id));
		if(result) heapFree(value);
		return result;
	}
	inline bool ctlRoot::removeLambdaEvent(ctlMouseEventType eventType, unsigned id)
	{
		typedef ctlLambdaEventCallStruct<lamMouseEvent, ctlMouseEvent> type;
		type* value = reinterpret_cast<type*>(id);
		bool result = removeEvent(eventType, type::eventDeal,
			reinterpret_cast<ctlMouseEvent::paramType>(id));
		if(result) heapFree(value);
		return result;
	}
	template<typename CastTo>
	inline CastTo ctlRoot::castTo()
	{
		static_assert(std::is_pointer<CastTo>::value,
			"CastTo 不是指针无法转换");
		if(getControlType() == std::remove_pointer<CastTo>::type::uniqueType)
			return reinterpret_cast<CastTo>(_control_virtual_class_end);
		return nullptr;
	}
	template<typename CastTo>
	inline CastTo control_cast(ctlRoot* object)
	{
		return object->castTo<CastTo>();
	}
	template<typename CastTo>
	inline CastTo& control_cast(ctlRoot& object)
	{
		typedef typename std::remove_reference<CastTo>::type *pointer;
		pointer ptr = control_cast<pointer>(&object);
		if(ptr != nullptr) return *ptr;
		throw std::bad_cast();
	}
}

#endif
